home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / 3.2v4 / fold < prev    next >
Encoding:
AWK Script  |  1997-08-26  |  9.4 KB  |  284 lines

  1. #!/usr/local/bin/gawk -f
  2. # fold: wrap lines
  3. # @(#) fold.gawk 1.0 94/03/08
  4. # 91/05/24 john h. dubois iii (john@armory.com)
  5. # 92/02/16 added help
  6. # 94/03/08 Converted to gawk script
  7.  
  8. # SCO UNIX 3.2v4.2 awk says its record limit is 3000 chars.
  9. # gawk 2.15 says it has no limits.
  10.  
  11. BEGIN {
  12.     Name = "fold"
  13.     Usage = "Usage: " Name " [-hw] [-<width>] [file ...]"
  14.     ARGC = Opts(Name,Usage,"hw&>",0)
  15.     MaxLine = 80 + 0
  16.     if ("h" in Options) {
  17.     printf \
  18. Name ": fold long lines.\n"\
  19. Usage "\n"\
  20. Name \
  21. " inserts newlines as neccessary to make long lines into multiple lines.\n"\
  22. "Options:\n"\
  23. "-h: Print this help.\n"\
  24. "-w: Try to fold at the last word-end before the length limit.\n"\
  25. "-<width>: Set the folding point to <width> characters.  The default is %s.\n",
  26.     MaxLine
  27.     exit(0)
  28.     }
  29.     if ("&" in Options)
  30.     MaxLine = Options["&"] + 0
  31.     Word = "w" in Options
  32. }
  33.  
  34. {
  35.     if ((len = length($0)) <= MaxLine)
  36.     print $0
  37.     else {
  38.     if (Word) {
  39.         NumLines = SplitLine($0,Lines,MaxLine)
  40.         for (i = 1; i <= NumLines; i++)
  41.         print Lines[i]
  42.     }
  43.     else
  44.         for (Pos = 1; Pos <= len; Pos += MaxLine)
  45.         print substr($0,Pos,MaxLine)
  46.     }
  47. }
  48.  
  49. # Splits Line into lines with maximum length of MaxLen.
  50. # If WordChars is non-empty, words are split on characters other than
  51. # those in the set it describes, if possible.
  52. # The default for WordChars is:  a-zA-Z0-9_
  53. # Lines are split on a non-alphanum character if possible.
  54. # The lines are put into Lines with indices starting with 1.
  55. # The number of lines put in Lines is returned.
  56. function SplitLine(Line,Lines,MaxLen,WordChars,
  57. Len,WordChars,LineNum,MaxLine) {
  58.     if (WordChars == "")
  59.     WordChars = "a-zA-Z0-9_"
  60.     WordChars = "[" WordChars "]"
  61.     LineNum = 0
  62.     while (Len = length(Line)) {
  63.     Lines[++LineNum] = substr(Line,1,MaxLen)
  64.     if (substr(Line,MaxLen,2) ~ "^" WordChars WordChars) {
  65.         MaxLine = Lines[LineNum]
  66.         sub(WordChars "*$","",MaxLine)
  67.         if (MaxLine != "")
  68.         Lines[LineNum] = MaxLine
  69.     }
  70.     Line = substr(Line,length(Lines[LineNum]) + 1)
  71.     sub("^ *","",Lines[LineNum])
  72.     }
  73.     return LineNum
  74. }
  75.  
  76. # WrapLine: insert newlines into string S to convert it into multiple
  77. # lines of length Len.  A newline is not included at the end.
  78. # String Indent, which may be null, is prefixed to all lines.
  79. # It is not included in the calculation of Len; the returned strings
  80. # will have a maximum length of Len + length(Indent).
  81. function WrapLine(S,Len,Indent,   NumLines,Lines,LineNum,Fmtd) {
  82.     NumLines = SplitLine(S,Lines,Len)
  83.     for (LineNum = 1; LineNum < NumLines; LineNum++)
  84.     Fmtd = Fmtd Indent Lines[LineNum] "\n"
  85.     Fmtd = Fmtd Indent Lines[LineNum]
  86.     return Fmtd
  87. }
  88.  
  89. # @(#) ProcArgs 1.2 94/03/08
  90. # 92/02/29 john h. dubois iii
  91. # 93/07/18 Added "#" arg type
  92. # 93/09/26 Don't count -h against MinArgs
  93. # 94/01/01 Stop scanning at first non-option arg.  Added '>' option type.
  94. #          Removed meaning of '+' or '-' by itself.
  95. # 94/03/08 Added & option and *()< option types.
  96.  
  97. # optlist is a string which contains all of the possible command line options.
  98. # A character followed by certain characters indicates that the option takes
  99. # an argument, with type as follows:
  100. # :    String argument
  101. # *    Floating point argument
  102. # (    Non-negative floating point argument
  103. # )    Positive floating point argument
  104. # #    Integer argument
  105. # <    Non-negative integer argument
  106. # >    Positive integer argument
  107. # The only difference the type of argument makes is in the runtime argument
  108. # error checking that is done.
  109.  
  110. # The & option is a special case used to get numeric options without the
  111. # user having to give an option character.  It is shorthand for [-+.0-9].
  112. # If & is included in optlist and an option string that begins with one of
  113. # these characters is seen, the value given to "&" will include the first
  114. # char of the option.  & must be followed by a type character other than ':'.
  115. # Note that if e.g. &> is given, an option of -.5 will produce an error.
  116.  
  117. # Strings in argv[] which begin with "-" or "+" are taken to be
  118. # strings of options, except that a string which consists solely of "-"
  119. # or "+" is taken to be a non-option string; like other non-option strings,
  120. # it stops the scanning of argv and is left in argv[].
  121. # If an option takes an argument, the argument may either immedately
  122. # follow it or be given separately.
  123.  
  124. # If an option that does not take an argument is given,
  125. # an index with its name is created in options and its value is set to "1".
  126. # If an option that does take an argument is given,
  127. # an index with its name is created in options and its value
  128. # is set to the value of the argument given for it.
  129. # Options and their arguments are deleted from argv.
  130. # Note that this means that there may be gaps  left in the indices of argv[].
  131. # If compress is nonzero, argv[] is packed by moving its elements so that
  132. # they have contiguous integer indices starting with 0.
  133. # argv[0] is not examined.
  134. # An argument of "--" or "++" stops the scanning of argv[].
  135. # The number of arguments left in argc is returned.
  136. # If an error occurs, the string OptErr is set to an error message and -1 is
  137. # returned.
  138. function ProcArgs(argc,argv,optlist,options,compress,
  139. ArgNum,ArgsLeft,Arg,ArgLen,ArgInd,Option,Pos,Err,NumOpt) {
  140. # ArgNum is the index of the argument being processed.
  141. # ArgsLeft is the number of arguments left in argv.
  142. # Arg is the argument being processed.
  143. # ArgLen is the length of the argument being processed.
  144. # ArgInd is the position of the character in Arg being processed.
  145. # Option is the character in Arg being processed.
  146. # Pos is the position in optlist of the option being processed.
  147. # NumOpt is true if a numeric option may be given.
  148.     ArgsLeft = argc
  149.     NumOpt = index(optlist,"&")
  150.     for (ArgNum = 1; ArgNum < argc; ArgNum++) {
  151.     if ((Arg = argv[ArgNum]) !~ /^[-+]./)    # Not an option; quit
  152.         break
  153.     delete argv[ArgNum]
  154.     ArgsLeft--
  155.     if ((Arg == "--") || (Arg == "++"))
  156.         break
  157.     ArgLen = length(Arg)
  158.     for (ArgInd = 2; ArgInd <= ArgLen; ArgInd++) {
  159.         Option = substr(Arg,ArgInd,1)
  160.         if (NumOpt && Option ~ /[-+.0-9]/) {
  161.         Option = "&"
  162.         Arg = "&" Arg
  163.         ArgLen++
  164.         Pos = NumOpt
  165.         }
  166.         else if (!(Pos = index(optlist,Option)) || Option == "&") {
  167.         OptErr = "Invalid option: -" Option
  168.         return -1
  169.         }
  170.         # If option takes a value...
  171.         if ((ArgType = substr(optlist,Pos + 1,1)) ~ "[:*()#<>]") {
  172.         if (ArgInd < ArgLen)    # Value is included with option
  173.             options[Option] = substr(Arg,ArgInd + 1)
  174.         else {    # Value is the next arg after option
  175.             if (ArgNum < (argc - 1)) {
  176.             options[Option] = argv[++ArgNum]
  177.             delete argv[ArgNum]
  178.             ArgsLeft--
  179.             }
  180.             else {
  181.             OptErr = "option requires an argument -- " Option
  182.             return -1
  183.             }
  184.         }
  185.         if ((Err = CheckType(ArgType,options[Option],Option)) != "") {
  186.             OptErr = Err
  187.             return -1
  188.         }
  189.         break    # Used up this option
  190.         }
  191.         else
  192.         options[Option] = 1
  193.     }
  194.     }
  195.     if (compress != 0)
  196.     PackArr(argv,ArgsLeft)
  197.     return ArgsLeft
  198. }
  199.  
  200. # :    String argument
  201. # *    Floating point argument
  202. # (    Non-negative floating point argument
  203. # )    Positive floating point argument
  204. # #    Integer argument
  205. # <    Non-negative integer argument
  206. # >    Positive integer argument
  207. function CheckType(ArgType,Value,Option,  Err) {
  208.     if (ArgType == ":")
  209.     return ""
  210.     # A number begins with option + or -, and is followed by a string of
  211.     # digits or a decimal with digits before it, after it, or both
  212.     if (Value !~ /^[-+]?([0-9]+|[0-9]+?\.[0-9]+|[0-9]+\.)$/)
  213.     Err = "must be a number"
  214.     else if (ArgType ~ "[#<>]" && Value ~ /\./)
  215.     Err = "may not include a fraction"
  216.     else if (ArgType ~ "[()<>]" && Value < 0)
  217.     Err = "may not be negative"
  218.     else if (ArgType ~ "[)>]" && Value == 0)
  219.     Err = "must be a positive number"
  220.     if (Err != "") {
  221.     if (Option == "&")
  222.         Option = Value
  223.     return "Option -" Option " " Err
  224.     }
  225.     else
  226.     return ""
  227. }
  228.  
  229. # Packs Arr to indices starting with 0
  230. # Num should be the number of elements in Arr
  231. function PackArr(Arr,Num,  NewInd,OldInd) {
  232.     NewInd = OldInd = 0
  233.     for (; Num; Num--) {
  234.     while (!(OldInd in Arr))
  235.         OldInd++
  236.     if (NewInd != OldInd) {
  237.         Arr[NewInd] = Arr[OldInd]
  238.         delete Arr[OldInd]
  239.     }
  240.     OldInd++
  241.     NewInd++
  242.     }
  243. }
  244.  
  245. # Opts: Process command line arguments.
  246. # Opts processes command line arguments using ProcArgs()
  247. # and checks for errors.  If an error occurs, a message is printed
  248. # and the program is exited.
  249. #
  250. # Input variables:
  251. # Name is the name of the program, for error messages.
  252. # Usage is a usage message, for error messages.
  253. # OptList the option description string, as used by ProcArgs().
  254. # MinArgs is the minimum number of non-option arguments that this
  255. # program should have, non including ARGV[0] and +h.
  256. # If the program does not require any non-option arguments,
  257. # MinArgs should be omitted or given as 0.
  258.  
  259. # Global variables:
  260. # The command line arguments are taken from ARGV[].
  261. # The arguments that are option specifiers and values are removed from
  262. # ARGV[], leaving only ARGV[0] and the non-option arguments.
  263. # The number of elements in ARGV[] should be in ARGC.
  264. # After processing, ARGC is set to the number of elements left in ARGV[].
  265. # The option values are put in Options[].
  266. # On error, Err is set to 1 so it can be checked for in an END block.
  267.  
  268. # Return value: The number of elements left in ARGV is returned.
  269.  
  270. function Opts(Name,Usage,OptList,MinArgs,  ArgsLeft) {
  271.     if (MinArgs == "")
  272.     MinArgs = 0
  273.     ArgsLeft = ProcArgs(ARGC,ARGV,OptList,Options,1)
  274.     if ((ArgsLeft + ("h" in Options)) < (MinArgs+1)) {
  275.     if (ArgsLeft != -1)
  276.         OptErr = "Not enough arguments"
  277.     print Name ": " OptErr ".  Use -h for help."
  278.     print Usage
  279.     Err = 1
  280.     exit 1
  281.     }
  282.     return ArgsLeft
  283. }
  284.